#include <assert.h>
#include "SimpleIo.h"
#include "MethodInfo.h"
#include "ConstantPool.h"
#include "Log.h"

void MethodInfo::assemble(u1 opcode)
{
  assert(code);
  code->assemble(opcode);
}

void MethodInfo::assemble(u1 opcode, u4 operand)
{
  assert(code);
  code->assemble(opcode,operand);
}

MethodInfo::MethodInfo(ConstantPool * cp, FILE *f)
{
  assert(cp);
  assert(f);

  constantPool=cp;

  long int at;
  at=ftell(f);

  code=0;
  access_flags=readUint16(f);
  name_index=readUint16(f);
  assert(cp->isUtf8At(name_index));
  signature_index=readUint16(f);
  assert(cp->isUtf8At(signature_index));

  LOG_LOAD("At %ld loading method '%s'\n",at,cp->getCString(name_index));

  u2 acount;
  acount=readUint16(f);
  AttributeInfo * ai;
  for(u2 i=0;i<acount;i++) {
    attributes.push_back(ai=AttributeInfoFactory::fromFile(cp,f));
    if(ai->tag==aie_code) 
      code=(AttributeInfoCode*)ai;
  }
  assert(code);
}

void MethodInfo::resetCode()
{
  code->resetCode();
}

MethodInfo::MethodInfo(ConstantPool * cp, const char * name, 
    const char * signature, u2 access_flags)
{
  assert(cp);
  assert(name);
  assert(signature);

  this->access_flags=access_flags;
  this->name_index=cp->addUtf8(name);
  this->signature_index=cp->addUtf8(signature);
  this->constantPool=cp;

  AttributeInfoCode * ac=new AttributeInfoCode(cp);
  code=ac;
  attributes.push_back(ac);
}

void assemblePrintStringStatement(const char * string)
{

}

void MethodInfo::save(FILE *f)
{
  assert(constantPool);
  LOG_SAVE("at %ld saving method '%s'\n",
      ftell(f),constantPool->getCString(name_index));
  writeUint16(f,access_flags);
  writeUint16(f,name_index);
  writeUint16(f,signature_index);
  writeUint16(f,attributes.size());
  LOG_SAVE("at %ld saving method '%s' attributes\n",
      ftell(f),constantPool->getCString(name_index));
  for(u2 i=0;i<attributes.size();i++)
    attributes[i]->save(f,constantPool);
}

const char * MethodInfo::getName()
{
  return constantPool->getCString(name_index);
}

const char * MethodInfo::getSignature()
{
  return constantPool->getCString(signature_index);
}

//void MethodInfo::dump(ConstantPool * cp)
void MethodInfo::dump()
{
  printf("Name: '");
  constantPool->getAt(name_index)->dump(constantPool);
  printf("' | Signature: '");
  constantPool->getAt(signature_index)->dump(constantPool);
  printf("' | Access flags: "); printAccessFlags(access_flags);
  printf("\n");
  printf("  disassemble:\n");
  if(code)
    code->disassemble(constantPool);
}
